home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / hplip / base / pkit.py < prev    next >
Encoding:
Python Source  |  2011-12-02  |  15.6 KB  |  493 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Stan Dolson
  20. #
  21.  
  22. # Std Lib
  23. import os
  24. import os.path
  25. import sys
  26. import re
  27. import time
  28. import cStringIO
  29. import ConfigParser
  30. import shutil
  31. import stat
  32.  
  33. # Local
  34. from base.logger import *
  35. from base.g import *
  36. from base.codes import *
  37. from base import utils, device
  38.  
  39. # DBus
  40. import dbus
  41. import dbus.service
  42. import gobject
  43.  
  44. import warnings
  45. # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters
  46. # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04)
  47. warnings.simplefilter("ignore", DeprecationWarning)
  48.  
  49.  
  50. class AccessDeniedException(dbus.DBusException):
  51.     _dbus_error_name = 'com.hp.hplip.AccessDeniedException'
  52.  
  53. class UnsupportedException(dbus.DBusException):
  54.     _dbus_error_name = 'com.hp.hplip.UnsupportedException'
  55.  
  56. class UsageError(dbus.DBusException):
  57.     _dbus_error_name = 'com.hp.hplip.UsageError'
  58.  
  59.  
  60. POLICY_KIT_ACTION = "com.hp.hplip"
  61. INSTALL_PLUGIN_ACTION = "com.hp.hplip.installplugin"
  62.  
  63.  
  64. def get_service_bus():
  65.     return dbus.SystemBus()
  66.  
  67.  
  68. def get_service(bus=None):
  69.     if not bus:
  70.         bus = get_service_bus()
  71.  
  72.     service = bus.get_object(BackendService.SERVICE_NAME, '/')
  73.     service = dbus.Interface(service, BackendService.INTERFACE_NAME)
  74.     return service
  75.  
  76.  
  77. class PolicyKitAuthentication(object):
  78.     def __init__(self):
  79.         super(PolicyKitAuthentication, self).__init__()
  80.         self.pkit = None
  81.         self.auth = None
  82.  
  83.  
  84.     def is_authorized(self, action_id, pid=None):
  85.         if pid == None:
  86.             pid = os.getpid()
  87.  
  88.         pid = dbus.UInt32(pid)
  89.  
  90.         authorized = self.policy_kit.IsProcessAuthorized(action_id, pid, False)
  91.         log.debug("is_authorized(%s) = %r" % (action_id, authorized))
  92.  
  93.         return (authorized == 'yes')
  94.  
  95.  
  96.     def obtain_authorization(self, action_id, widget=None):
  97.         if self.is_authorized(action_id):
  98.             return True
  99.  
  100.         xid = (widget and widget.get_toplevel().window.xid or 0)
  101.         xid, pid = dbus.UInt32(xid), dbus.UInt32(os.getpid())
  102.  
  103.         granted = self.auth_agent.ObtainAuthorization(action_id, xid, pid)
  104.         log.debug("obtain_authorization(%s) = %r" % (action_id, granted))
  105.  
  106.         return bool(granted)
  107.  
  108.  
  109.     def get_policy_kit(self):
  110.         if self.pkit:
  111.             return self.pkit
  112.  
  113.         service = dbus.SystemBus().get_object('org.freedesktop.PolicyKit', '/')
  114.         self.pkit = dbus.Interface(service, 'org.freedesktop.PolicyKit')
  115.         return self.pkit
  116.  
  117.     policy_kit = property(get_policy_kit)
  118.  
  119.  
  120.     def get_auth_agent(self):
  121.         if self.auth:
  122.             return self.auth
  123.  
  124.         self.auth = dbus.SessionBus().get_object(
  125.             'org.freedesktop.PolicyKit.AuthenticationAgent', '/')
  126.         return self.auth
  127.  
  128.     auth_agent = property(get_auth_agent)
  129.  
  130.  
  131.  
  132. class PolicyKitService(dbus.service.Object):
  133.     def check_permission_v0(self, sender, action=POLICY_KIT_ACTION):
  134.         if not sender:
  135.             log.error("Session not authorized by PolicyKit")
  136.             raise AccessDeniedException('Session not authorized by PolicyKit')
  137.  
  138.         try:
  139.             policy_auth = PolicyKitAuthentication()
  140.             bus = dbus.SystemBus()
  141.  
  142.             dbus_object = bus.get_object('org.freedesktop.DBus', '/')
  143.             dbus_object = dbus.Interface(dbus_object, 'org.freedesktop.DBus')
  144.  
  145.             pid = dbus.UInt32(dbus_object.GetConnectionUnixProcessID(sender))
  146.  
  147.             granted = policy_auth.is_authorized(action, pid)
  148.             if not granted:
  149.                 log.error("Process not authorized by PolicyKit")
  150.                 raise AccessDeniedException('Process not authorized by PolicyKit')
  151.  
  152.             granted = policy_auth.policy_kit.IsSystemBusNameAuthorized(action,
  153.                                                                        sender,
  154.                                                                        False)
  155.             if granted != 'yes':
  156.                 log.error("Session not authorized by PolicyKit version 0")
  157.                 raise AccessDeniedException('Session not authorized by PolicyKit')
  158.  
  159.         except AccessDeniedException:
  160.             log.warning("AccessDeniedException")
  161.             raise
  162.  
  163.         except dbus.DBusException, ex:
  164.             log.warning("AccessDeniedException %r", ex)
  165.             raise AccessDeniedException(ex.message)
  166.  
  167.  
  168.     def check_permission_v1(self, sender, connection, action=POLICY_KIT_ACTION):
  169.         if not sender or not connection:
  170.             log.error("Session not authorized by PolicyKit")
  171.             raise AccessDeniedException('Session not authorized by PolicyKit')
  172.  
  173.         system_bus = dbus.SystemBus()
  174.         obj = system_bus.get_object("org.freedesktop.PolicyKit1",
  175.                                     "/org/freedesktop/PolicyKit1/Authority",
  176.                                     "org.freedesktop.PolicyKit1.Authority")
  177.         policy_kit = dbus.Interface(obj, "org.freedesktop.PolicyKit1.Authority")
  178.         info = dbus.Interface(connection.get_object("org.freedesktop.DBus",
  179.                                                     "/org/freedesktop/DBus/Bus",
  180.                                                     False),
  181.                               "org.freedesktop.DBus")
  182.         pid = info.GetConnectionUnixProcessID(sender)
  183.         
  184.         subject = (
  185.             'unix-process',
  186.             { 'pid' : dbus.UInt32(pid, variant_level = 1) }
  187.         )
  188.         details = { '' : '' }
  189.         flags = dbus.UInt32(1)         # AllowUserInteraction = 0x00000001
  190.         cancel_id = ''
  191.  
  192.         (ok, notused, details) = \
  193.             policy_kit.CheckAuthorization(subject,
  194.                                           action,
  195.                                           details,
  196.                                           flags,
  197.                                           cancel_id)
  198.         if not ok:
  199.             log.error("Session not authorized by PolicyKit version 1")
  200.  
  201.         return ok
  202.  
  203.  
  204. if utils.to_bool(sys_conf.get('configure', 'policy-kit')):
  205.     class BackendService(PolicyKitService):
  206.         INTERFACE_NAME = 'com.hp.hplip'
  207.         SERVICE_NAME   = 'com.hp.hplip'
  208.         LOGFILE_NAME   = '/tmp/hp-pkservice.log'
  209.  
  210.         def __init__(self, connection=None, path='/', logfile=LOGFILE_NAME):
  211.             if connection is None:
  212.                 connection = get_service_bus()
  213.  
  214.             super(BackendService, self).__init__(connection, path)
  215.  
  216.             self.name = dbus.service.BusName(self.SERVICE_NAME, connection)
  217.             self.loop = gobject.MainLoop()
  218.             self.version = 0
  219.  
  220.             log.set_logfile("%s.%d" % (logfile, os.getpid()))
  221.             log.set_level("debug")
  222.  
  223.         def run(self, version=None):
  224.             if version is None:
  225.                 version = policykit_version()
  226.                 if version is None:
  227.                     log.error("Unable to determine installed PolicyKit version")
  228.                     return
  229.  
  230.             self.version = version
  231.             log.set_where(Logger.LOG_TO_CONSOLE_AND_FILE)
  232.             log.debug("Starting back-end service loop (version %d)" % version)
  233.  
  234.             self.loop.run()
  235.  
  236.  
  237.         @dbus.service.method(dbus_interface=INTERFACE_NAME,
  238.                                 in_signature='s', out_signature='b',
  239.                                 sender_keyword='sender',
  240.                                 connection_keyword='connection')
  241.         def installPlugin(self, src_dir, sender=None, connection=None):
  242.             if self.version == 0:
  243.                 try:
  244.                     self.check_permission_v0(sender, INSTALL_PLUGIN_ACTION)
  245.                 except AccessDeniedException, e:
  246.                     return False
  247.  
  248.             elif self.version == 1:
  249.                 if not self.check_permission_v1(sender,
  250.                                                 connection,
  251.                                                 INSTALL_PLUGIN_ACTION):
  252.                     return False
  253.  
  254.             else:
  255.                 log.error("installPlugin: invalid PolicyKit version %d" % self.version)
  256.                 return False
  257.  
  258.             log.debug("installPlugin: installing from '%s'" % src_dir)
  259.  
  260.             if not copyPluginFiles(src_dir):
  261.                 log.error("Plugin installation failed")
  262.                 return False
  263.  
  264.             return True
  265.  
  266.  
  267.         @dbus.service.method(dbus_interface=INTERFACE_NAME,
  268.                                 in_signature='s', out_signature='b',
  269.                                 sender_keyword='sender',
  270.                                 connection_keyword='connection')
  271.         def shutdown(self, arg, sender=None, connection=None):
  272.             log.debug("Stopping backend service")
  273.             self.loop.quit()
  274.  
  275.             return True
  276.  
  277.  
  278.  
  279. class PolicyKit(object):
  280.     def __init__(self, version=None):
  281.         if version is None:
  282.             version = policykit_version()
  283.             if version is None:
  284.                 log.debug("Unable to determine installed PolicyKit version")
  285.                 return
  286.  
  287.         self.bus = dbus.SystemBus()
  288.         self.obj = self.bus.get_object(POLICY_KIT_ACTION, "/")
  289.         self.iface = dbus.Interface(self.obj, dbus_interface=POLICY_KIT_ACTION)
  290.         self.version = version
  291.  
  292.     def installPlugin(self, src_dir):
  293.         if self.version == 0:
  294.             auth = PolicyKitAuthentication()
  295.             if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
  296.                 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
  297.                     return None
  298.  
  299.         try:
  300.             ok = self.iface.installPlugin(src_dir)
  301.             return ok
  302.         except dbus.DBusException, e:
  303.             log.debug("installPlugin: %s" % str(e))
  304.             return False
  305.  
  306.  
  307.     def shutdown(self):
  308.         if self.version == 0:
  309.             auth = PolicyKitAuthentication()
  310.             if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
  311.                 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
  312.                     return None
  313.  
  314.         try:
  315.             ok = self.iface.shutdown("")
  316.             return ok
  317.         except dbus.DBusException, e:
  318.             log.debug("shutdown: %s" % str(e))
  319.             return False
  320.  
  321.  
  322.  
  323. def copyPluginFiles(src_dir):
  324.     os.chdir(src_dir)
  325.  
  326.     plugin_spec = ConfigBase("plugin.spec")
  327.     products = plugin_spec.keys("products")
  328.  
  329.     BITNESS = utils.getBitness()
  330.     ENDIAN = utils.getEndian()
  331.     PPDDIR = sys_conf.get('dirs', 'ppd')
  332.     DRVDIR = sys_conf.get('dirs', 'drv')
  333.     HOMEDIR = sys_conf.get('dirs', 'home')
  334.     DOCDIR = sys_conf.get('dirs', 'doc')
  335.     CUPSBACKENDDIR = sys_conf.get('dirs', 'cupsbackend')
  336.     CUPSFILTERDIR = sys_conf.get('dirs', 'cupsfilter')
  337.     RULESDIR = '/etc/udev/rules.d'
  338.  
  339.     processor = utils.getProcessor()
  340.     if processor == 'power_machintosh':
  341.         ARCH = 'ppc'
  342.     else:
  343.         ARCH = 'x86_%d' % BITNESS
  344.  
  345.     if BITNESS == 64:
  346.         SANELIBDIR = '/usr/lib64/sane'
  347.         LIBDIR = '/usr/lib64'
  348.     else:
  349.         SANELIBDIR = '/usr/lib/sane'
  350.         LIBDIR = '/usr/lib'
  351.  
  352.     copies = []
  353.  
  354.     for PRODUCT in products:
  355.         MODEL = PRODUCT.replace('hp-', '').replace('hp_', '')
  356.         for s in plugin_spec.get("products", PRODUCT).split(','):
  357.  
  358.             if not plugin_spec.has_section(s):
  359.                 log.error("Missing section [%s]" % s)
  360.                 return False
  361.  
  362.             src = plugin_spec.get(s, 'src', '')
  363.             trg = plugin_spec.get(s, 'trg', '')
  364.             link = plugin_spec.get(s, 'link', '')
  365.  
  366.             if not src:
  367.                 log.error("Missing 'src=' value in section [%s]" % s)
  368.                 return False
  369.  
  370.             if not trg:
  371.                 log.error("Missing 'trg=' value in section [%s]" % s)
  372.                 return False
  373.  
  374.             src = os.path.basename(utils.cat(src))
  375.             trg = utils.cat(trg)
  376.  
  377.             if link:
  378.                 link = utils.cat(link)
  379.  
  380.             copies.append((src, trg, link))
  381.  
  382.     copies = utils.uniqueList(copies)
  383.     copies.sort()
  384.  
  385.     os.umask(0)
  386.  
  387.     for src, trg, link in copies:
  388.  
  389.         if not os.path.exists(src):
  390.             log.debug("Source file %s does not exist. Skipping." % src)
  391.             continue
  392.  
  393.         if os.path.exists(trg):
  394.             log.debug("Target file %s already exists. Replacing." % trg)
  395.             os.remove(trg)
  396.  
  397.         trg_dir = os.path.dirname(trg)
  398.  
  399.         if not os.path.exists(trg_dir):
  400.             log.debug("Target directory %s does not exist. Creating." % trg_dir)
  401.             os.makedirs(trg_dir, 0755)
  402.  
  403.         if not os.path.isdir(trg_dir):
  404.             log.error("Target directory %s exists but is not a directory. Skipping." % trg_dir)
  405.             continue
  406.  
  407.         try:
  408.             shutil.copyfile(src, trg)
  409.         except (IOError, OSError), e:
  410.             log.error("File copy failed: %s" % e.strerror)
  411.             continue
  412.  
  413.         else:
  414.             if not os.path.exists(trg):
  415.                 log.error("Target file %s does not exist. File copy failed." % trg)
  416.                 continue
  417.             else:
  418.                 os.chmod(trg, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH)
  419.  
  420.             if link:
  421.                 if os.path.exists(link):
  422.                     log.debug("Symlink already exists. Replacing.")
  423.                     os.remove(link)
  424.  
  425.                 log.debug("Creating symlink %s (link) to file %s (target)..." %
  426.                     (link, trg))
  427.  
  428.                 try:
  429.                     os.symlink(trg, link)
  430.                 except (OSError, IOError), e:
  431.                     log.debug("Unable to create symlink: %s" % e.strerror)
  432.                     pass
  433.  
  434.     log.debug("Updating hplip.conf - installed = 1")
  435.     sys_state.set('plugin', "installed", '1')
  436.     log.debug("Updating hplip.conf - eula = 1")
  437.     sys_state.set('plugin', "eula", '1')
  438.  
  439.     return True
  440.  
  441.  
  442. def run_plugin_command(required=True, plugin_reason=PLUGIN_REASON_NONE):
  443.     su_sudo = None
  444.     need_sudo = True
  445.  
  446.     if utils.to_bool(sys_conf.get('configure', 'policy-kit')):
  447.         try:
  448.             obj = PolicyKit()
  449.             su_sudo = "%s"
  450.             need_sudo = False
  451.             log.debug("Using PolicyKit for authentication")
  452.         except dbus.DBusException, ex:
  453.             log.error("PolicyKit NOT installed when configured for use")
  454.  
  455.     if os.geteuid() == 0:
  456.         su_sudo = "%s"
  457.         need_sudo = False
  458.  
  459.     password_f = None
  460.     if need_sudo:
  461.         su_sudo = utils.su_sudo()
  462.     if su_sudo is "su":
  463.         su_sudo = 'su -c "%s"'
  464.         password_f = "get_password_ui"    
  465.     if su_sudo is None:
  466.         log.error("Unable to find a suitable sudo command to run 'hp-plugin'")
  467.         return (False, False)
  468.  
  469.     req = '--required'
  470.     if not required:
  471.         req = '--optional'
  472.  
  473.     if utils.which("hp-plugin"):
  474.         cmd = su_sudo % ("hp-plugin -u %s --reason %s" % (req, plugin_reason))
  475.     else:
  476.         cmd = su_sudo % ("python ./plugin.py -u %s --reason %s" % (req, plugin_reason))
  477.  
  478.     log.debug("%s" % cmd)
  479.     if password_f is not None:
  480.         status, output = utils.run(cmd, log_output=True, password_func=password_f, timeout=1)
  481.     else:
  482.         status, output = utils.run(cmd, log_output=True, password_func=None, timeout=1)
  483.     return (status == 0, True)
  484.  
  485.  
  486. def policykit_version():
  487.     if os.path.isdir("/usr/share/polkit-1"):
  488.         return 1
  489.     elif os.path.isdir("/usr/share/PolicyKit"):
  490.         return 0
  491.     else:
  492.         return None
  493.